home *** CD-ROM | disk | FTP | other *** search
- /*
- ** Apple Macintosh Developer Technical Support
- **
- ** Routines common to a sound decompressor and compressor.
- **
- ** by Mark Cookson, Apple Developer Technical Support
- **
- ** File: Common.c
- **
- ** Copyright ©1996 Apple Computer, Inc.
- ** All rights reserved.
- **
- ** You may incorporate this sample code into your applications without
- ** restriction, though the sample code has been provided "AS IS" and the
- ** responsibility for its operation is 100% yours. However, what you are
- ** not permitted to do is to redistribute the source as "Apple Sample
- ** Code" after having made changes. If you're going to re-distribute the
- ** source, we require that you make it clear in the source that the code
- ** was descended from Apple Sample Code, but that you've made changes.
- */
-
- #define kSoundComponentVersion 0x00010000 // version for this sound component
- #define kRequiredSndMgrMajorRev 3 // Sound Manager version required to run this component
-
- #define kOutputSampleSize 16 // output sample size
-
- //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- // Call in the component dispatcher code
- //
- // Main Component Entry Point is the component dispacher code
- //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- #include "ComponentDispatch.c"
-
- #if !GENERATINGPOWERPC
- //----------------------------------------------------------------------------------
- // main
- //----------------------------------------------------------------------------------
- pascal ComponentResult main( ComponentParameters *params, SoundComponentGlobalsPtr globals );
- pascal ComponentResult main( ComponentParameters *params, SoundComponentGlobalsPtr globals )
- {
- return (SoundComponentEntryPoint(params,globals));
- }
- #endif
-
- //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- // Component Manager Methods
- //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- /* ==============================================================================
- Component Open
-
- This routine is called when the Component Manager creates an instance of this
- component. The routine should allocate global variables in the appropriate heap
- and call SetComponentInstanceStorage() so the Component Manager can remember
- the globals and pass them to all the method calls.
-
- Determining the heap to use can be tricky. The Component Manager will normally
- load the component code into the system heap, which is good, since many applications
- will be sharing this component to play sound. In this case, the components's global
- variable storage should also be created in the system heap.
-
- However, if system heap memory is tight, the Component Manager will load
- the component into the application heap of the first application that plays sound.
- When this happens, the component should create global storage in the application heap
- instead. The Sound Manager will make sure that other applications will not try
- to play sound while the component is in this application heap.
-
- To determine the proper heap to use, call GetComponentInstanceA5(). If the value
- returned is 0, then the component was loaded into the system heap, and all storage
- should be allocated there. If the value returned is non-zero, the component is in
- the application heap specifed by returned A5 value, and all storage should be
- allocated in this application heap.
-
- NOTE: If the component is loaded into the application heap, the value returned by
- GetComponentRefCon() will be 0.
- NOTE: Do not attempt to initialize in this call, since the Component Manager will
- call Open() BEFORE calling Register().
- NOTE: This routine is never called at interrupt time.
- ============================================================================== */
-
- pascal ComponentResult __SoundComponentOpen(void *unused1, ComponentInstance self)
- {
- #pragma unused (unused1)
-
- Handle h;
- SoundComponentGlobalsPtr globals;
-
- h = NewHandleClear(sizeof(SoundComponentGlobals)); // get space for globals
- if (h == nil)
- return(MemError());
-
- HLock(h);
- globals = (SoundComponentGlobalsPtr) *h;
- SetComponentInstanceStorage (self, (Handle) globals); // save pointer to our globals
-
- globals->globalsHandle = h; // remember the handle
- globals->thisComponent.format = kOutputSampleFormat; // output sample format
- globals->thisComponent.sampleSize = kOutputSampleSize; // output sample size
- globals->outputSamples = kMaxOutputSamples; // size of our output buffer
-
- return (noErr);
- }
-
- /* ==============================================================================
- Component Close
-
- This routine is called when the Component Manager is closing the instance of
- this component. It should delete all global storage and close any other components
- that were opened.
-
- NOTE: Be sure to check that the globals pointer passed in to this routine is
- not set to NIL. If the Open() routine fails for any reason, the Component
- Manager will call this routine passing in a NIL for the globals.
- NOTE: This routine is never called at interrupt time.
- ============================================================================== */
-
- pascal ComponentResult __SoundComponentClose(SoundComponentGlobalsPtr globals, ComponentInstance self)
- {
- #pragma unused (self)
-
- if (globals) // we have some globals
- {
- if (globals->sourceComponent) // we have a source component
- CloseComponent(globals->sourceComponent); // close it
-
- globals->thisComponent.sampleCount = 0; // nothing in our buffer now
- DisposeHandle(globals->globalsHandle); // dispose our storage
- }
-
- return (noErr);
- }
-
- /* ==============================================================================
- Component Register
-
- This routine is called once, usually at boot time, when the Component Manager
- is first registering this sound component. This routine should check to see if the proper
- Sound Manager is installed and return 0 if it is. If the right Sound Manager is not
- installed, the routine should return 1 and this component will not be registered.
-
- NOTE: The cmpWantsRegisterMessage bit must be set in the component flags of the
- sound component in order for this routine to be called.
- NOTE: This routine is never called at interrupt time.
- ============================================================================== */
-
- pascal ComponentResult __SoundComponentRegister(SoundComponentGlobalsPtr globals)
- {
- #pragma unused (globals)
-
- long result;
- NumVersion version;
-
- if ((Gestalt(gestaltSoundAttr, &result) == noErr) && // snd gestalt is available
- (result & (1L << gestaltSoundIOMgrPresent))) // snd dispatcher is available
- {
- version = SndSoundManagerVersion(); // get the Sound Manager version
- if (version.majorRev >= kRequiredSndMgrMajorRev) // it's what we need
- {
- return (0); // install this compression component
- }
- }
-
- return (1); // do not install component
- }
-
- /* ==============================================================================
- GetInfo
-
- This routine returns information about this output component to the Sound Manager.
- A 4-byte OSType selector is used to determine the type and size of the information
- to return. If the component does not support a selector, it should delegate this
- call on up the chain.
-
- NOTE: This can be called at interrupt time. However, selectors that return
- a handle will not be called at interrupt time.
- ============================================================================== */
-
- pascal ComponentResult __SoundComponentGetInfo(SoundComponentGlobalsPtr globals, SoundSource sourceID,
- OSType selector, void *infoPtr)
- {
- ComponentResult result = noErr;
-
- switch (selector)
- {
- case siCompressionFactor:
- GetCompressorInfo(infoPtr); // fill out the CompressionInfo structure passed in
- break;
-
- default:
- result = SoundComponentGetInfo(globals->sourceComponent, sourceID, selector, infoPtr);
- break;
- }
-
- return (result);
- }
-
- /* ==============================================================================
- StopSource
-
- This routine is used to stop sounds that are currently playing. It should
- clear out any internal buffers, reset any compression state information
- and then delegate the call up the chain.
-
- NOTE: This can be called at interrupt time.
- ============================================================================== */
-
- pascal ComponentResult __SoundComponentStopSource(SoundComponentGlobalsPtr globals, short count, SoundSource *sources)
- {
- globals->sourceDataPtr = nil; // clear out internal buffers
- globals->thisComponent.sampleCount = 0; // our buffer is empty
- #ifdef COMPRESSION
- InitializeCompressor(globals); // initialize our compressor state
- #else
- InitializeDecompressor(globals); // initialize our compressor state
- #endif
- return (SoundComponentStopSource(globals->sourceComponent, count, sources)); // delegate this call
- }
-
- /* ==============================================================================
- PlaySourceBuffer
-
- This routine is used to start a new sound playing. It should clear out any internal buffers
- but should NOT reset any compression state information, since this could be a
- continuation of a sound that has been broken into pieces. Then the call should be
- delegated up the chain.
-
- NOTE: This can be called at interrupt time.
- ============================================================================== */
-
- pascal ComponentResult __SoundComponentPlaySourceBuffer(SoundComponentGlobalsPtr globals, SoundSource sourceID, SoundParamBlockPtr pb, long actions)
- {
- globals->sourceDataPtr = nil; // clear out internal buffers
- globals->thisComponent.sampleCount = 0; // our buffer is empty
-
- return (SoundComponentPlaySourceBuffer(globals->sourceComponent, sourceID, pb, actions)); // delegate this call
- }
-
-